var accessToken = "139436992894387|65471b8b3fdc60240f6b3a9e14284c1f";
var board = new Array(8);
var playersPictures = new Array(2);
var lastPlayerInChat;
var numberOfChatMessages = 0;
var draggingChatWindow = false;
var dragChatX;
var dragChatY;
var chatOriginalRight;
var chatOriginalBottom;
var droppableSquares = new Array(8);
var players;
var me;
var lastMessage;

function initialize(){
	playersPictures[0] = "images/checkers/user_picture.gif";
	playersPictures[1] = "images/checkers/user_picture.gif";

	createWebSocketConnection();
	initializeBoard();
	createPieces();
	resetDragNDrop();
	bindChatWindow();
	
	$("#chat_send").bind("keypress", function(event){
		if (event.keyCode == 13){
			sendChatMessage($("#chat_send").val());
			$("#chat_send").val("");
		}
	});
}
/***********************
/* Websocket functions *
/***********************/

function createWebSocketConnection(){
	ws = new WebSocket("ws://localhost:8080/playground/WebSocketServlet/checkers");
	ws.onopen = function(event) {
		console.log("connection opened");
		var msg = {action: "registerPlayerToSocket", playerId: $.cookie("playerId"), playerKey: $.cookie("playerKey")};
		ws.send(JSON.stringify(msg));
		console.log("message sent: " + JSON.stringify(msg));
	};
	
	ws.onerror = function(event) {
		console.log("an erro has occured");
		console.log(event);
	};
	
	ws.onmessage = function(event) {
		console.log("message received");
		console.log("json::: " + event.data);
		var data = jQuery.parseJSON(event.data);
		//console.log("object::: " + data);
		if (data.success){
			switch(data.action){
				case "registerPlayerToSocket":
					console.log("player registration succeeded " + data.loggedPlayer.facebookId + " " + data.loggedPlayer.status);
					/*var msg = {action: "registerRoomToSocket", roomId: getURLParameter("roomId")};
					ws.send(JSON.stringify(msg));
					console.log("message sent: " + JSON.stringify(msg));*/
					break;
				case "startGame":
					console.log("player registration succeeded for everyone, game started");
					players = data.players;
					me = getPlayerById($.cookie("playerId"));
					createFacebookData(players[0]);
					createFacebookData(players[1]);
					writeFacebookData();
					setPlayerInTurn(players[0]);
					break;
				case "writeToChat":
					writeInChat(getPlayerById(data.senderId), data.text);
					break;
				case "yourTurn":
					setPlayerInTurn(me);
					setDraggable(data.movablePieces);
					break;
				case "makeMove":
					// move the piece
					if (me.id != data.playerId){
						movePiece(getPieceInSquare(getSquareByPosition(data.sourceSquarePosition)), getSquareByPosition(data.destinationSquarePosition), function(){
							executeReactions(data);
						});
					} else{
						executeReactions(data);
					}
					// set the player in turn
					setPlayerInTurn(getPlayerById(data.playerInTurnId));
			}
		} else{
			console.log("'" + data.action + "' failed.");
		}
		
	};
		
	ws.onclose = function(event) {
		console.log("connection closed");
	};
}

function executeReactions(data){
	// remove the piece if a piece was removed in server
	if (data.removed !== undefined){
		removePiece(getPieceInSquare(getSquareByPosition(data.removed)), function(){
			// if the game is over
			if (data.gameOver){
				if (data.winnerId == me.id) gameOver(true);
				else gameOver(false);
			}
		});
	}
	// if the game is over
	else if (data.gameOver){
		if (data.winnerId == me.id) gameOver(true);
		else gameOver(false)
	}
	// the moved piece became a king?
	if (data.kinged){
		kingPiece(getPieceInSquare(getSquareByPosition(data.destinationSquarePosition)));
	}
	
}

function getURLParameter(name) {
    return decodeURI(
        (RegExp(name + '=' + '(.+?)(&|$)').exec(location.search)||[,null])[1]
    );
}

function createFacebookData(player){
	var query = player.facebookId + "?fields=name,picture";
	var jsonUrl = "https://graph.facebook.com/" + query + "&access_token=" + accessToken;
	
	$.ajax({
		type: 'GET',
		url: jsonUrl,
		dataType: 'json',
		success: function(data){
			player.username = data.name;
			player.picture = data.picture.data.url;
		},
		data: {},
		async: false
	});
}

function writeFacebookData(){
	$("#facebook_username_white").html(players[0].username);
	$("#facebook_picture_white").attr("src", players[0].picture);
	$("#facebook_username_black").html(players[1].username);
	$("#facebook_picture_black").attr("src", players[1].picture);
}

function setPlayerInTurn(player){
	var index = players.indexOf(player);
	if (index == 0){
		$("#player_white_rectangle").attr("class", "pwr_active");
		$("#player_black_rectangle").attr("class", "pbr_inactive");
	} else{
		$("#player_white_rectangle").attr("class", "pwr_inactive");
		$("#player_black_rectangle").attr("class", "pbr_active");
	}
}

function getPlayerById(id){
	for(var i = 0; i < players.length; i++){
		if (players[i].id == id){
			return players[i];
		}
	}
}

function setDraggable(movablePieces){
	for(var key in movablePieces){
		var piece = getPieceInSquare(getSquareByPosition(key));
		var movableTo = new Array();
		for (var i = 0; i < movablePieces[key].length; i++){
			//console.log(key + ", " + target);
			movableTo.push(getSquareByPosition(movablePieces[key][i]));
		}
		//console.log("draggable:: piece: " + piece + "; movableTo: " + movableTo);
		setPieceDraggable(piece, movableTo);
	}
}

function getSquareByPosition(pos){
	var row = Math.floor(pos / 8);
	var col = pos % 8;
	return board[row][col];
}

function getPieceInSquare(square){
	return $(square).find("div")[0];
}

function gameOver(win){
	$("#modal").show();
	$("#leave_room").show();
	$("#endgame_message").addClass(win ? "win" : "lose");
	$("#endgame_message").show();
	$("#modal").bind("click", leaveRoomAfterGameIsOver);
	$("#endgame_message").bind("click", leaveRoomAfterGameIsOver);
}

function leaveRoomAfterGameIsOver(){
	// send message to end room
	ws.close();
	window.location.replace("gamehub.html");
}

/**************************************
/* Websockets: send message functions *
/**************************************/

function sendChatMessage(string){
	var message = {action: "writeToChat", text: string};
	ws.send(JSON.stringify(message));
}

function sendMoveMessage(previousRow, previousCol, newRow, newCol){
	var message = {
		action: "makeMove",
		sourceSquarePosition: previousRow * 8 + previousCol,
		destinationSquarePosition: newRow * 8 + newCol
	};
	console.log(ws.readyState);
	ws.send(JSON.stringify(message));
	lastMessage = JSON.stringify(message);
	console.log("message sent: " + JSON.stringify(message));
}

/*****************************************
/* Board functions: board initialization *
/*****************************************/

function initializeBoard(){
	var divs = $("div[id^='square']");
	for (var i = 0; i < 8; i++){
		board[i] = new Array(8);
	}
	for (var i = 0; i < divs.length; i++){
		// register in board
		var values = $(divs[i]).attr("id").split(":"); 
		var row = values[1];
		var col = values[2];
		board[row][col] = divs[i];
		
		// make it droppable
		$(divs[i]).droppable({
			drop: handlePieceDropEvent,
			accept: function (draggable){
				return isDroppable($(this).attr("id"), $(draggable).attr("id"));
			}
		});
	}
	
	for (var i = 0; i < 8; i++){
		droppableSquares[i] = new Array(8);
	}
}

function resetDragNDrop(){
	for (var i = 0; i < 8; i++){
		for (var j = 0; j < 8; j++){
			droppableSquares[i][j] = new Array();
		}
	}
	
	var pieces = $("div[id^='piece']");
	for (var i = 0; i < pieces.length; i++){
		disableDragNDrop(pieces[i]);
	}
}

function createPieces(){
	var piece = 0;
	
	$(board[0][0]).html(generatePiece(0, piece++));
	$(board[0][2]).html(generatePiece(0, piece++));
	$(board[0][4]).html(generatePiece(0, piece++));
	$(board[0][6]).html(generatePiece(0, piece++));
	
	$(board[1][1]).html(generatePiece(0, piece++));
	$(board[1][3]).html(generatePiece(0, piece++));
	$(board[1][5]).html(generatePiece(0, piece++));
	$(board[1][7]).html(generatePiece(0, piece++));
	
	$(board[2][0]).html(generatePiece(0, piece++));
	$(board[2][2]).html(generatePiece(0, piece++));
	$(board[2][4]).html(generatePiece(0, piece++));
	$(board[2][6]).html(generatePiece(0, piece++));

	$(board[5][1]).html(generatePiece(1, piece++));
	$(board[5][3]).html(generatePiece(1, piece++));
	$(board[5][5]).html(generatePiece(1, piece++));
	$(board[5][7]).html(generatePiece(1, piece++));
	
	$(board[6][0]).html(generatePiece(1, piece++));
	$(board[6][2]).html(generatePiece(1, piece++));
	$(board[6][4]).html(generatePiece(1, piece++));
	$(board[6][6]).html(generatePiece(1, piece++));
	
	$(board[7][1]).html(generatePiece(1, piece++));
	$(board[7][3]).html(generatePiece(1, piece++));
	$(board[7][5]).html(generatePiece(1, piece++));
	$(board[7][7]).html(generatePiece(1, piece++));
	
	var pieces = $("div[id^='piece']");
	for (var i = 0; i < pieces.length; i++){
		$(pieces[i]).draggable({
			containment: "#board",
			revert: true
		});
	}
}

/****************************************
/* Board functions: board modifications *
/****************************************/

function setPieceDraggable(piece, droppableList){
	enableDragNDrop(piece);
	for (var i = 0; i < droppableList.length; i++){
		// console.log("making " + $(droppableList[i]).attr("id") + " droppable");
		var decomposedSquareId = $(droppableList[i]).attr("id").split(":");
		var squareRow = decomposedSquareId[1];
		var squareCol = decomposedSquareId[2];
		var pieceIndex = parseInt($(piece).attr("id").split(":")[1]);
		droppableSquares[squareRow][squareCol].push(pieceIndex);
	}
}

// receives the dom elements, not the ids
function movePiece(piece, targetSquare, postAnimationFunction){
	var sourceSquare = $(piece).parent();
	var decomposedSourceSquareId = $(sourceSquare).attr("id").split(":");
	var sourceRow = decomposedSourceSquareId[1];
	var sourceCol = decomposedSourceSquareId[2];
	var decomposedTargetSquareId = $(targetSquare).attr("id").split(":");
	var targetRow = decomposedTargetSquareId[1];
	var targetCol = decomposedTargetSquareId[2];
	
	var leftMovement = 65 * (targetCol - sourceCol);
	var topMovement = 65 * (targetRow - sourceRow);
	
	var options = {
		left: "+=" + leftMovement,
		top: "+=" + topMovement
	};
	
	$(piece).animate(options, 500 * (Math.abs(targetCol - sourceCol) + Math.abs(targetRow - sourceRow)), function(){
		$(this).detach().css({top: 0,left: 0}).appendTo(targetSquare);
		if (postAnimationFunction !== undefined){
			postAnimationFunction();
		}
	});
}

// the dom element
function removePiece(piece, postAnimationFunction){
	var numberPieces = $(piece).hasClass("white_piece") ? $("#white_number_pieces") : $("#black_number_pieces");
	var oldNumber = parseInt($(numberPieces).html());
	$(numberPieces).html(oldNumber - 1);
	if ($(piece).hasClass("kinged")){
		var numberKings = $(piece).hasClass("white_piece") ? $("#white_number_kings") : $("#black_number_kings");
		oldNumber = parseInt($(numberKings).html());
		$(numberKings).html(oldNumber - 1);
	}
	$(piece).animate({opacity: 0}, 2000, function(){
		$(piece).remove();
		if (postAnimationFunction !== undefined){
			postAnimationFunction();
		}
	});
}

function kingPiece(piece){
	var crown;
	if ($(piece).hasClass("white")){
		numberKings = $("#white_number_kings");
		crown = "crown_black.png";
	} else{
		numberKings = $("#black_number_kings");
		crown = "crown_white.png";
	}
	oldNumber = parseInt($(numberKings).html());
	$(numberKings).html(oldNumber + 1);
	$(piece).html("<img src=\"images/checkers/" + crown + "\" alt=\"kinged\" />");
	
}

function isDroppable(droppable, draggable){
	var decomposedDroppableId = droppable.split(":");
	var droppableRow = decomposedDroppableId[1];
	var droppableCol = decomposedDroppableId[2];
	var draggablePiece = parseInt(draggable.split(":")[1]);
	// console.log("drop? (" + droppableRow + ", " + droppableCol + "); looking for: " + draggablePiece + "; result: " + $.inArray(draggablePiece, droppableSquares[droppableRow][droppableCol]));
	return (-1 != $.inArray(draggablePiece, droppableSquares[droppableRow][droppableCol]));
}

function handlePieceDropEvent(event, ui){
	ui.draggable.draggable( 'option', 'revert', false );
	var dropped = ui.draggable;
	var droppedOn = $(this);
	var previousSquareDecomposedId = $(dropped).parent().attr("id").split(":");
	var previousRow = previousSquareDecomposedId[1];
	var previousCol = previousSquareDecomposedId[2];
	var newSquareDecomposedId = $(droppedOn).attr("id").split(":");
	var newRow = newSquareDecomposedId[1];
	var newCol = newSquareDecomposedId[2];
	$(dropped).detach().css({top: 0,left: 0}).appendTo(droppedOn);
	resetDragNDrop();
	sendMoveMessage(parseInt(previousRow), parseInt(previousCol), parseInt(newRow), parseInt(newCol));
}

/****************************************************************
/* Board functions: utility functions (used by other functions) *
/****************************************************************/

function testDragNDrop(){
	setPieceDraggable(($(board[2][0]).find("div"))[0], [board[3][1]]);
	setPieceDraggable(($(board[2][2]).find("div"))[0], [board[3][1], board[3][3]]);
	setPieceDraggable(($(board[2][4]).find("div"))[0], [board[3][3], board[3][5]]);
	setPieceDraggable(($(board[2][6]).find("div"))[0], [board[3][5], board[3][7]]);
}

function generatePiece(color, index){
	if (color == 0){
		return "<div id=\"piece:" + index + "\" class=\"piece white\" alt=\"white piece\" />";
	}
	return "<div id=\"piece:" + index + "\" class=\"piece black\" alt=\"black piece\" />";
}

function enableDragNDrop(piece){
	//$(piece).addClass("ui-draggable");
	$(piece).draggable("option", "revert", true);
	$(piece).draggable("enable");
}

function disableDragNDrop(piece){
	//$(piece).removeClass("ui-draggable");
	$(piece).draggable("disable");
}

/******************
/* Chat functions *
/******************/

function writeInChat(player, message){
	if (lastPlayerInChat == player){
		$("#message\\:" + (numberOfChatMessages - 1)).append("<p>" + message + "<p>");
	} else{
		if ($("#chat_content").html() != ""){
			$("#chat_content").append("<div class=\"chat_separator\"></div>");
		}
		var messageId = "message:" + numberOfChatMessages++;
		var html = "<div id=\"" + messageId + "\" class=\"chat_message\">";
		html += "<img src=\"" + player.picture + "\" width=\"30\" height=\"30\" alt=\"" + player.username + " said: \" />";
		html += "<p>" + message + "<p>";
		html += "</div>";
		$("#chat_content").append(html);
		lastPlayerInChat = player;
	}
}

function moveChatWindow(xOffset, yOffset){
	$("#chat").css("bottom", (parseInt(chatOriginalBottom) + yOffset) + "px");
	$("#chat").css("right", (parseInt(chatOriginalRight) + xOffset) + "px");
}

function bindChatWindow(){
	$("#chat_move_icon").click(function(event){
		if(!draggingChatWindow){
			chatOriginalRight = $("#chat").css("right").split("px")[0];
			chatOriginalBottom = $("#chat").css("bottom").split("px")[0];
			dragChatX = event.pageX;
			dragChatY = event.pageY;
			draggingChatWindow = true;
			event.stopPropagation();
		}
	});
	$("body").mousemove(function(event){
		if(draggingChatWindow){
			moveChatWindow(dragChatX - event.pageX, dragChatY - event.pageY);
		}
	});
	$("body").click(function(event){
		draggingChatWindow = false;
	});
}